using UnityEngine;
using System.IO;
using System.Text;
using System;
using System.Collections.Generic;
using LitJson;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using System.Linq;

namespace TCC.Framework
{
    /// <summary>
    /// 文件操作
    /// </summary>
    public static class FileOperations
    {
        /// <summary>
        /// 路径暂存列表
        /// </summary>
        static List<string> paths = new List<string>();

        #region Json
        /// <summary>
        /// 写入Json数据
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="path">文件完整路径</param>
        public static void WriteJsonData(object data, string path)
        {
            string json = JsonMapper.ToJson(data);
            WriteData(json, path);
        }

        /// <summary>
        /// 读取Json数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="path">数据完整路径</param>
        /// <returns></returns>
        public static T ReadJsonData<T>(string path)
        {
            return JsonMapper.ToObject<T>(ReadText(path));
        }
        #endregion

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="value">要写入的数据</param>
        /// <param name="path">数据完整路径</param>
        public static void WriteData(string value, string path)
        {
            //打开或者新建文档
            using (StreamWriter sw = new StreamWriter(path))
            {
                //保存数据
                sw.WriteLine(value);
                //关闭文档
                sw.Close();
                sw.Dispose();
            }
        }

        /// <summary>
        /// 以二进制形式写入数据
        /// </summary>
        /// <param name="obj">数据</param>
        /// <param name="path">数据完整路径</param>
        public static void WriteBinaryData(System.Object obj,string path)
        {
            try
            {
                string folderPath = path.Remove(path.LastIndexOf('/'));
                if (!Directory.Exists(folderPath))
                    Directory.CreateDirectory(folderPath);
                BinaryFormatter binary = new BinaryFormatter();
                using(FileStream fs=File.Create(path))
                {
                    binary.Serialize(fs, obj);
                }
            }catch(Exception e)
            {
                Log.Error(e.Message);
            }
            
        }

        /// <summary>
        /// 读取二进制文件
        /// </summary>
        /// <typeparam name="T">文件类型</typeparam>
        /// <param name="path">文件路径</param>
        /// <returns></returns>
        public static T ReadBinaryData<T>(string path)
        {
            try
            {
                BinaryFormatter binary = new BinaryFormatter();
                using(FileStream fs=File.Open(path,FileMode.Open))
                {
                    return (T)binary.Deserialize(fs);
                }
            }catch(Exception e)
            {
                Log.Info(e.Message);
                return default(T);
            }
        }

        public static byte[] SafeReadAllBytes(string inFile)
        {
            try
            {
                if (string.IsNullOrEmpty(inFile)|| !File.Exists(inFile))
                    return null;

                File.SetAttributes(inFile, FileAttributes.Normal);
                return File.ReadAllBytes(inFile);
            }
            catch (System.Exception ex)
            {
                Log.Error(string.Format("SafeReadAllBytes failed! path = {0} with err = {1}", inFile, ex.Message));
                return null;
            }
        }

        /// <summary>
        /// 读取文本数据
        /// </summary>
        /// <param name="path">数据完整路径</param>
        /// <returns></returns>
        public static string ReadText(string path)
        {
            if (!File.Exists(path)) return null;

            using (StreamReader str = new StreamReader(path, Encoding.UTF8))
            {
                if (str == null) return null;
                return str.ReadToEnd();
            }
        }

        /// <summary>
        /// 获取文件夹下所有文件路径
        /// </summary>
        /// <param name="dir">文件夹路径</param>
        /// <param name="excludeFile">要排除的文件的后缀</param>
        /// <returns></returns>
        public static string[] GetFolderAllFilePath(string dir,params string[] excludeFile)
        {
            paths.Clear();
            FindFile(dir, excludeFile);
            return paths.ToArray();
        }

        static void FindFile(string dir, params string[] excludeFile)
        {
            DirectoryInfo info = new DirectoryInfo(dir);
            FileSystemInfo[] file = info.GetFileSystemInfos();
            foreach (var item in file)
            {
                if (item is DirectoryInfo)
                    FindFile(item.FullName,excludeFile);
                else
                {
                    if (excludeFile != null)
                    {
                        string suffix = item.Extension;
                        bool isAdd = true;
                        
                        foreach (var su in excludeFile)
                        {
                            if (suffix == su)
                                isAdd = false;
                        }
                        if (isAdd)
                            paths.Add(item.FullName);
                    }
                    else
                        paths.Add(item.FullName);
                }
            }
        }

        /// <summary>
        /// 获取路径下所有文件夹路径
        /// </summary>
        /// <param name="path">路径</param>
        /// <returns></returns>
        public static string[] GetPathAllFolders(string path)
        {
            paths.Clear();
            FindFolders(path);
            return paths.ToArray();
        }

        static void FindFolders(string path)
        {
            DirectoryInfo info = new DirectoryInfo(path);
            FileSystemInfo[] file = info.GetFileSystemInfos();
            foreach (var item in file)
            {
                if (item is DirectoryInfo)
                {
                    FindFolders(item.FullName);
                    paths.Add(item.FullName);
                }
            }
        }

        /// <summary>
        /// 拷贝文件夹
        /// </summary>
        /// <param name="sourceDirName"></param>
        /// <param name="destDirName"></param>
        public static void CopyDirectory(string sourceDirName, string destDirName)
        {
            try
            {
                if (!Directory.Exists(destDirName))
                {
                    Directory.CreateDirectory(destDirName);
                    File.SetAttributes(destDirName, File.GetAttributes(sourceDirName));
                }

                if (destDirName[destDirName.Length - 1] != Path.DirectorySeparatorChar)
                    destDirName = destDirName + Path.DirectorySeparatorChar;

                string[] files = Directory.GetFiles(sourceDirName);
                foreach (string file in files)
                {
                    if (File.Exists(destDirName + Path.GetFileName(file)))
                        continue;
                    FileInfo fileInfo = new FileInfo(file);
                    if (fileInfo.Extension.Equals(".meta", StringComparison.CurrentCultureIgnoreCase))
                        continue;

                    File.Copy(file, destDirName + Path.GetFileName(file), true);
                    File.SetAttributes(destDirName + Path.GetFileName(file), FileAttributes.Normal);
                }

                string[] dirs = Directory.GetDirectories(sourceDirName);
                foreach (string dir in dirs)
                {
                    CopyDirectory(dir, destDirName + Path.GetFileName(dir));
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 检查文件路径是否存在
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static bool FileExists(string path) => File.Exists(path);

        /// <summary>
        /// 检查文件夹是否存在
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static bool FolderExists(string path) => Directory.Exists(path);

        /// <summary>
        /// 获取文件夹下指定类型文件信息
        /// </summary>
        /// <param name="folder">文件夹</param>
        /// <param name="suffix">后缀</param>
        /// <returns></returns>
        public static FileInfo[] GetFiles(string folder,string suffix)
        {
            if (!Directory.Exists(folder)) return null;

            DirectoryInfo di = new DirectoryInfo(folder);
            return di.GetFiles().ToList().Where(p=>p.Extension==suffix).Select(p=>p).ToArray();
        }

        /// <summary>
        /// 获取文件夹下指定类型文件信息
        /// </summary>
        /// <param name="folder">文件夹</param>
        /// <param name="suffix">后缀</param>
        /// <returns></returns>
        public static FileInfo[] GetFiles(string folder, string suffix,IComparer comparer)
        {
            if (!Directory.Exists(folder)) return null;

            DirectoryInfo di = new DirectoryInfo(folder);
            FileInfo[] fileInfo= di.GetFiles().ToList().Where(p => p.Extension == suffix).Select(p => p).ToArray();
            Array.Sort(fileInfo, comparer);
            return fileInfo;
        }

        /// <summary>
        /// 按时间排序
        /// </summary>
        /// <returns></returns>
        public static IComparer SortToTime => new FileTimeComparer();

        public class FileTimeComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                FileInfo file1 = x as FileInfo;
                FileInfo file2 = y as FileInfo;
                return file1.LastWriteTime.CompareTo(file2.LastWriteTime);
            }
        }
    }
}
